package WizardTD;

import WizardTD.board.Board;
import WizardTD.board.ManaProcessBar;
import WizardTD.constant.Constant;
import WizardTD.constant.ImageConstant;
import WizardTD.constant.TextConstant;
import WizardTD.element.*;
import WizardTD.element.Element;
import WizardTD.element.Fireball;
import WizardTD.element.Tower;
import WizardTD.element.MonsterBox;
import WizardTD.enums.ButtonEnum;
import lombok.Data;
import processing.core.PApplet;

import java.util.*;
import java.util.List;

/**
 * @author HustleLr
 * @version 1.0.0
 */
@Data
public class ElementDraw {
    private List<Wave> waves;
    private PApplet pApplet;
    private DataConstruct dataConstruct;


    public ElementDraw(LevelAndWaveConfig levelAndWaveConfig, PApplet pApplet, DataConstruct dataConstruct) {
        this.waves = levelAndWaveConfig.getWaves();
        this.pApplet = pApplet;
        this.dataConstruct = dataConstruct;
    }


    /**
     * 构建画布
     *
     * @param dataConstruct 数据
     */
    public void startGame(DataConstruct dataConstruct) {
        // 波数与怪兽列表
        Map<Integer, CountdownTimer> countdownTimerMap = dataConstruct.getCountdownTimerMap();
        LevelAndWaveConfig levelAndWaveConfig = dataConstruct.levelAndWaveConfig;
        CountdownTimer countdownTimer = new CountdownTimer(0);
        if (App.waveNum < levelAndWaveConfig.getWaves().size()) {
            countdownTimer = countdownTimerMap.get(App.waveNum);
        }
        int speed = App.board.getChoiceButtons().contains(ButtonEnum.FF) ? 2 : 1;
        for (int i = 0; i < speed; i++) {
            generateBackground(dataConstruct, countdownTimer);
            behavior();
            generateElement();
            ManaProcessBar manaProcessBar = App.board.getManaProcessBar();
            if (manaProcessBar.getCurrentMana() <= 0) {
                this.shutdownGame(TextConstant.LOSE);
            }
            if (App.monsterBox.getMonsters().isEmpty()
                    && App.monsterBox.getRemoveMonsters().size() == levelAndWaveConfig.getAllMonsterNums()){
                this.shutdownGame(TextConstant.SUCCESS);
            }
        }
//        drawMonster(dataConstruct.getShortestPath());
    }

    /**
     * 行为
     */
    private void behavior() {
        decideShoot(App.towers, App.monsterBox.getMonsters());
        decideAttack(App.monsterBox.getMonsters(), App.fireballs);
    }

    /**
     * 生成元素
     */
    private void generateElement() {
        drawPlaceTower();
        drawElement(App.towers);
        drawElement(App.fireballs, App.removeFireballs);
        drawMonster(App.monsterBox);
    }

    /**
     * 生成背景
     *
     * @param dataConstruct  数据构造
     * @param countdownTimer 计时器
     */
    private static void generateBackground(DataConstruct dataConstruct, CountdownTimer countdownTimer) {
        App.board.drawTop(dataConstruct.getLevelAndWaveConfig().getWaveNums(), (int) countdownTimer.getCurrentTime());
        App.board.drawRight();
        App.board.drawBoard(dataConstruct);
    }

    public void shutdownGame(String tip) {
        CountdownTimer countdownTimer = new CountdownTimer(999);
        generateBackground(dataConstruct, countdownTimer);
        int transparentRed = pApplet.color(0, 0, 0, 128);
        pApplet.fill(transparentRed);
        pApplet.noStroke();
        pApplet.rect(0, App.CELLSIZE + 8, App.WIDTH, App.HEIGHT);
        pApplet.textSize(36);
        pApplet.text(tip, (float) (App.WIDTH-App.SIDEBAR*2) / 2, (float) App.HEIGHT / 2);
        pApplet.noLoop();
    }

    private void drawMonster(MonsterBox monster) {
        monster.drawMonster();
    }

    private void decideShoot(List<Tower> towers, List<Monster> monsters) {
        for (Tower tower : towers) {
            boolean flag = tower.decideShoot(monsters);
            tower.setShootFlag(flag);
        }
    }

    private void decideAttack(List<Monster> monsters, List<Fireball> fireballs) {
        for (Fireball fireball : fireballs) {
            fireball.decideAttack(monsters);
        }
    }


    private void drawElement(List<? extends Element> elements) {
        for (Element element : elements) {
            element.draw(pApplet);
        }
    }

    private void drawElement(List<? extends Element> elements, List<? extends Element> removeElements) {
        elements.removeAll(removeElements);
        removeElements.clear();
        for (Element element : elements) {
            element.draw(pApplet);
        }
    }


    private void drawPlaceTower() {
        float mouseX = pApplet.mouseX;
        float mouseY = pApplet.mouseY;

        if (App.board.getChoiceButtons().contains(ButtonEnum.T)) {
            pApplet.tint(255, 160);
            if (!isAllowPlace(mouseX, mouseY, 32, App.board)) {
                pApplet.fill(255, 0, 0, 100);
            } else {
                pApplet.fill(0, 128, 0, 100);
            }
            pApplet.ellipse(mouseX, mouseY, Constant.initialTowerRange * 2, Constant.initialTowerRange * 2);
            pApplet.image(ImageConstant.tower0, mouseX - 16, mouseY - 16);
            pApplet.tint(255, 255);
        }
    }

    private boolean isAllowPlace(float mouseX, float mouseY, float side, Board board) {
        return board.isGrass(mouseX, mouseY, side) && board.getTower(mouseX, mouseY) == null;
    }

}
